using behaviac;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using System;
using System.Collections.Generic;

namespace IQIGame.Onigao.GamePlay
{
    /// <summary>
    /// Behaviac全局自定义数据中心
    /// </summary>
    public class BehaviacGlobal : Singleton<BehaviacGlobal>
    {
        private Dictionary<int, BehaviacManager> _managers = new Dictionary<int, BehaviacManager>();
        private Dictionary<string, byte[]> _allConfigs = new Dictionary<string, byte[]>();
        private Dictionary<int, List<string>> _moduleMap = new Dictionary<int, List<string>>();
        private Dictionary<string, int> _pathCount = new Dictionary<string, int>();
        private static int _idGen;
        private bool _isActive;

        public Func<string, byte[]> loadConfig { get; private set; }

        private BehaviacGlobal() { }

        /// <summary>
        /// 初始化
        /// </summary>
        public void Init(Func<string, byte[]> loadConfigFunc)
        {
            if (_isActive)
            {
                return;
            }
            _isActive = true;

            loadConfig = loadConfigFunc;

            //用自定义Loader覆盖behaviac.FileManager的单例
            CustomBehaviacLoader.CoverLoader();

            //设置behaviac Workspace必要的初始值
            Workspace.Instance.FilePath = PathConstant.BehaviacCfgRoot; //状态机配置导出总目录，如果有不同的工作区，那么所有工作区都必须在这个目录下
            Workspace.Instance.MetaFile = PathConstant.BehaviacMetaName;
            Workspace.Instance.FileFormat = Workspace.EFileFormat.EFF_bson;

#if UNITY_EDITOR
            bool activeDebug = ManagerCenter.Behaviac.activeDebug;
            Config.IsSocketing = activeDebug;
            if (activeDebug)
            {
                Config.IsSocketBlocking = ManagerCenter.Behaviac.isSocketBlocking;
                Config.SocketPort = ManagerCenter.Behaviac.debugPort;
                ManagerCenter.MonoDriver.updateEvent += OnDebugUpdate;
            }
#elif !BEHAVIAC_RELEASE
            LogGame.LogError("当前行为树没有设置为发布模式，可能会产生严重的性能问题");
#endif

#if !LOGIC_SERVER
            ManagerCenter.MonoDriver.onApplicationQuitEvent += Shutdown;
#endif
        }

        /// <summary>
        /// 创建行为树管理器
        /// </summary>
        /// <param name="updateInterval">刷新时间（秒），-1代表每帧刷新</param>
        /// <returns></returns>
        public BehaviacManager CreateManager(float updateInterval)
        {
            int id = GenModuleId();
            BehaviacManager manager = new BehaviacManager(id, updateInterval);
            _managers[id] = manager;
            return manager;
        }

        public void ReleaseManager(BehaviacManager manager)
        {
            int id = manager.id;
            manager.Dispose();
            RemoveConfig(id);
            _managers.Remove(id);
        }

        /// <summary>
        /// 创建模块唯一id，用于一键清除所有缓存
        /// </summary>
        /// <returns></returns>
        private int GenModuleId()
        {
            return ++_idGen;
        }

        /// <summary>
        /// 添加模块和配置的映射关系以便管理
        /// </summary>
        /// <param name="path">全路径</param>
        /// <param name="content">配置的byte[]数据</param>
        /// <returns>是否添加成功</returns>
        public void AddPath(int id, string path)
        {
            //add module cache
            List<string> keys;
            if (!_moduleMap.TryGetValue(id, out keys))
            {
                keys = new List<string>();
                _moduleMap[id] = keys;
            }
            if (!keys.Contains(path))
            {
                keys.Add(path);
                if (_pathCount.TryGetValue(path, out int count))
                {
                    _pathCount[path] = count++;
                }
                else
                {
                    _pathCount[path] = 1;
                }
            }
        }

        /// <summary>
        /// 清除缓存，退出模块时调用
        /// </summary>
        /// <param name="id">模块唯一id，通过GenModuleId()创建，并通过AddConfig()传入</param>
        private void RemoveConfig(int id)
        {
            if (_moduleMap.TryGetValue(id, out List<string> list))
            {
                foreach (string path in list)
                {
                    int count;
                    if (_pathCount.TryGetValue(path, out count))
                    {
                        _pathCount[path] = count--;
                    }
                    if (count <= 0)
                    {
                        _allConfigs.Remove(path);
                    }
                    if (count < 0)
                    {
                        _pathCount[path] = 0;
                        LogGame.LogError($"Path count is error. path: {path}");
                    }
                }
                list.Clear();
                _moduleMap.Remove(id);
            }
        }

        /// <summary>
        /// 获取配置二进制数据，为自定义的behaviac.FileManager提供的方法
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public byte[] GetBtContent(string fileName)
        {
            byte[] content = null;
            if (_allConfigs.TryGetValue(fileName, out content))
            {
                return content;
            }

            try
            {
                content = loadConfig(fileName);
            }
            catch (Exception e)
            {
                LogGame.LogError(e);
            }

            if (content != null)
            {
                _allConfigs[fileName] = content;
            }

            return content;
        }

#if UNITY_EDITOR
        public void OnDebugUpdate(float deltaTime, float unscaledDeltaTime)
        {
            Workspace.Instance.DebugUpdate();
        }
#endif

        public void Shutdown()
        {
            if (!_isActive)
            {
                return;
            }
            _isActive = false;
#if !LOGIC_SERVER
            ManagerCenter.MonoDriver.onApplicationQuitEvent -= Shutdown;
#endif
            if (Workspace.Instance.IsInited)
            {
                Workspace.Instance.Cleanup();
            }
        }
    }
}
